package com.mapbased.sfw.util;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class Strings {

	public static Map<String, String> parseMapStr(String s) {
		Map<String, String> m = new HashMap<String, String>();
		parseMapStr(m, s);
		return m;
	}

	public static void parseMapStr(Map<String, String> m, String s) {
		String[] ss = s.split(";");
		for (String t : ss) {
			int i = t.indexOf("=");
			if (i > 0) {
				m.put(t.substring(0, i).trim(), t.substring(i + 1).trim());
			}
		}

	}

	public static StringBuilder quoteSafeJson(StringBuilder sb, String string) {
		return sb.append("\"").append(string).append("\"");

	}

	public static String quote(String string) {

		if (string == null || string.length() == 0) {
			return "\"\"";
		}

		char b;
		char c = 0;
		int i;
		int len = string.length();
		StringBuffer sb = new StringBuffer(len * 2);
		String t;
		char[] chars = string.toCharArray();
		char[] buffer = new char[1030];
		int bufferIndex = 0;
		sb.append('"');
		for (i = 0; i < len; i += 1) {
			if (bufferIndex > 1024) {
				sb.append(buffer, 0, bufferIndex);
				bufferIndex = 0;
			}
			b = c;
			c = chars[i];
			switch (c) {
			case '\\':
			case '"':
				buffer[bufferIndex++] = '\\';
				buffer[bufferIndex++] = c;
				break;
			case '/':
				if (b == '<') {
					buffer[bufferIndex++] = '\\';
				}
				buffer[bufferIndex++] = c;
				break;
			default:
				if (c < ' ') {
					switch (c) {
					case '\b':
						buffer[bufferIndex++] = '\\';
						buffer[bufferIndex++] = 'b';
						break;
					case '\t':
						buffer[bufferIndex++] = '\\';
						buffer[bufferIndex++] = 't';
						break;
					case '\n':
						buffer[bufferIndex++] = '\\';
						buffer[bufferIndex++] = 'n';
						break;
					case '\f':
						buffer[bufferIndex++] = '\\';
						buffer[bufferIndex++] = 'f';
						break;
					case '\r':
						buffer[bufferIndex++] = '\\';
						buffer[bufferIndex++] = 'r';
						break;
					default:
						t = "000" + Integer.toHexString(c);
						int tLength = t.length();
						buffer[bufferIndex++] = '\\';
						buffer[bufferIndex++] = 'u';
						buffer[bufferIndex++] = t.charAt(tLength - 4);
						buffer[bufferIndex++] = t.charAt(tLength - 3);
						buffer[bufferIndex++] = t.charAt(tLength - 2);
						buffer[bufferIndex++] = t.charAt(tLength - 1);
					}
				} else {
					buffer[bufferIndex++] = c;
				}
			}
		}
		sb.append(buffer, 0, bufferIndex);
		sb.append('"');
		return sb.toString();
	}

	public static StringBuilder quoteJson(StringBuilder sb, String s)

	{
		return sb.append(quote(s));
	}

	public static final String throwableToString(Throwable t) {
		// if (t instanceof WoyoException) {
		// return t.getMessage();
		// }
		ByteArrayOutputStream ba = new ByteArrayOutputStream();
		PrintWriter p = new PrintWriter(ba);
		t.printStackTrace(p);
		p.flush();
		return ba.toString();
	}

	public static String[] splitTwo(String s, char split) {
		if (s == null) {
			return new String[] { s };
		}
		int i = s.indexOf(split);
		if (i < 0) {
			return new String[] { s };
		}
		String[] r = new String[2];
		r[0] = s.substring(0, i);
		r[1] = s.substring(i + 1);
		return r;

	}

	/**
	 * for remote debug
	 * 
	 * @param o
	 * @param field
	 * @return
	 * @throws IllegalArgumentException
	 * @throws SecurityException
	 * @throws IllegalAccessException
	 * @throws NoSuchFieldException
	 */
	public static Object access(Object o, String field)
			throws IllegalArgumentException, SecurityException,
			IllegalAccessException, NoSuchFieldException {

		Class c = o.getClass();
		Field f = c.getDeclaredField(field);

		while (f == null) {

			c = c.getSuperclass();
			if (c == null) {
				break;
			}
			f = c.getDeclaredField(field);
		}

		f.setAccessible(true);
		return f.get(o);

	}

	/**
	 * for remote debug
	 * 
	 * @param o
	 * @param field
	 * @param sb
	 * @throws IllegalArgumentException
	 * @throws SecurityException
	 * @throws IllegalAccessException
	 * @throws NoSuchFieldException
	 */
	public static void printAccess(Object o, String field, StringBuilder sb)
			throws IllegalArgumentException, SecurityException,
			IllegalAccessException, NoSuchFieldException {

		print(access(o, field), sb);
	}

	/**
	 * for remote debug
	 * 
	 * @param o
	 * @param sb
	 */
	public static void print(Object o, StringBuilder sb) {

		if (o == null) {
			sb.append("null\n");
			return;
		}

		if (o.getClass().isArray()) {
			for (int i = 0; i < Array.getLength(o); i++) {
				sb.append(i).append("-->").append(Array.get(o, i)).append("\n");
				if (i > 5000) {
					sb.append("More than 5000 ,breaked\n");
					break;
				}
			}
		} else if (o instanceof Map) {
			Map m = (Map) o;
			int i = 0;
			for (Object e : m.entrySet()) {
				Map.Entry me = (Map.Entry) e;
				sb.append(me.getKey()).append("==>").append(me.getValue())
						.append("\n");
				if (i++ > 5000) {
					sb.append("More than 5000 ,breaked\n");
					break;
				}
			}
		} else if (o instanceof java.util.Collection) {

			print(((java.util.Collection) o).toArray(), sb);
		} else {

			sb.append(o.getClass().getName()).append("====>").append(o).append(
					"\n");
		}

	}
	
	
	 final public static String toXmlAttributeSafe(String s)
	    {
	        if(s == null)
	        {
	            return null;
	        }
	        StringBuffer sb=new StringBuffer(s.length() + 20);
	        for(int i=0;i < s.length();i++)
	        {
	            char c=s.charAt(i);
	            if(c == '<')
	            {
	                sb.append("&lt;");
	            }
	            else if(c == '>')
	            {
	                sb.append("&gt;");
	            }
	            else if(c == '&')
	            {
	                sb.append("&amp;");
	            }
	            else if(c == '"')
	            {
	                sb.append("&quot;");
	            }
	            else if(c == '\'')
	            {
	                sb.append("&#39;");
	            }
	          
	            else
	            {
	                sb.append(c);
	            }

	        }
	        return sb.toString();
	    }

	

	/**
	 * Converts some important chars (int) to the corresponding html string
	 */
	static String conv2Html(int i) {
		if (i == '&')
			return "&amp;";
		else if (i == '<')
			return "&lt;";
		else if (i == '>')
			return "&gt;";
		else if (i == '"')
			return "&quot;";
		else
			return "" + (char) i;
	}

	public final static void exec(String command, String dir, StringBuilder ret) {
		final String[] COMMAND_INTERPRETER = { "/bin/sh", "-c" };
		final long MAX_PROCESS_RUNNING_TIME = 30 * 1000; // 30 seconds

		String[] comm = new String[3];
		comm[0] = COMMAND_INTERPRETER[0];
		comm[1] = COMMAND_INTERPRETER[1];
		comm[2] = command;
		long start = System.currentTimeMillis();
		try {
			// Start process
			Process ls_proc = Runtime.getRuntime().exec(comm, null,
					new File(dir));
			// Get input and error streams
			BufferedInputStream ls_in = new BufferedInputStream(ls_proc
					.getInputStream());
			BufferedInputStream ls_err = new BufferedInputStream(ls_proc
					.getErrorStream());
			boolean end = false;
			while (!end) {
				int c = 0;
				while ((ls_err.available() > 0) && (++c <= 1000)) {
					ret.append(conv2Html(ls_err.read()));
				}
				c = 0;
				while ((ls_in.available() > 0) && (++c <= 1000)) {
					ret.append(conv2Html(ls_in.read()));
				}
				try {
					ls_proc.exitValue();
					// if the process has not finished, an exception is thrown
					// else
					while (ls_err.available() > 0)
						ret.append(conv2Html(ls_err.read()));
					while (ls_in.available() > 0)
						ret.append(conv2Html(ls_in.read()));
					end = true;
				} catch (IllegalThreadStateException ex) {
					// Process is running
				}
				// The process is not allowed to run longer than given time.
				if (System.currentTimeMillis() - start > MAX_PROCESS_RUNNING_TIME) {
					ls_proc.destroy();
					end = true;
					ret.append("!!!! Process has timed out, destroyed !!!!!");
				}
				try {
					Thread.sleep(50);
				} catch (InterruptedException ie) {
				}
			}
		} catch (IOException e) {
			ret.append("Error: " + e);
		}

	}

	public static final void arrayToString(StringBuilder sb, String name,
			Object[] os) {
		sb.append(name).append(":");
		if (os == null) {
			sb.append(" null \n");
			return;
		}
		sb.append("[");
		for (Object o : os) {
			sb.append(o).append(",");
		}
		sb.append("]\n");

	}

}
